// 该文件已被弃用，现在已使用 ../decorator 目录下拆分后的各装饰器文件
import { RequestHandler } from "express";
import router from '../router'

// 枚举类型
enum Methods {
  get = "get",
  post = "post",
}

// controller 是类装饰器
export function controller(target: any) {
  // controller 是类装饰器，接收参数是 constructor 的函数
  // 遍历原型链上的所有方法
  for (let key in target.prototype) {
    // 获取元数据
    // 获取 target.prototype 上，key 方法的 "path" 属性
    const path = Reflect.getMetadata("path", target.prototype, key);
    const method: Methods = Reflect.getMetadata("method", target.prototype, key);
    const handler = target.prototype[key];
    const middleware = Reflect.getMetadata("middleware", target.prototype, key);
    // 如果 target.prototype 上，的这个方法有 "path" 这个属性：
    if (path && method && handler) {
      // 判断这个路由是否使用了中间件
      if (middleware) {
        router[method](path, middleware, handler);
      } else {
        router[method](path, handler);
      }
    }
  }
}

// use 装饰器，该装饰器是一个工厂函数，传入的参数是 middleware
export function use(middleware: RequestHandler) {
  // 返回一个装饰器
  return function (target: any, key: string) {
    // 在 target 的 key 上，存储一个名为 'middleware' 值为 middleware 的元数据
    Reflect.defineMetadata("middleware", middleware, target, key);
  };
}

/**
 * 对 Reflect.defineMetadata(metadataKey,metadataValue, target, propertyKey) 的讲解：
 */
// export function get(path: string) {
//   // get 是一个方法装饰器工厂函数，需要返回一个接收参数为（原型，方法名，配置描述）格式的函数
//   return function (target: any, key: string) {
//     /**
//      * 创建一个自定义的元数据映射关系存储
//      * Reflect.defineMetadata(metadataKey,metadataValue, target, propertyKey)
//      * @param metadataKey 映射的key
//      * @param metadataValue 映射key 对应的value值
//      * @param target 映射需要的对应的类 或者实例
//      * @param propertyKey 实例上的属性
//      * **/
//     Reflect.defineMetadata("path", path, target, key);
//     // 当
//     // class LoginController {
//     //    @get("/login")
//     //    login() {}
//     // }
//     // 这样装饰时通过 Reflect.defineMetadata("path", path, target, key); 方法：
//     // 给 LoginController 类的原型上（target）的 login 方法名（key)，设置了名为 "path"，值为 "/login"（path）的元数据映射
//     // 存方法名
//     Reflect.defineMetadata("method", "get", target, key);
//   };
// }

// 工厂模式返回 方法装饰器工厂函数
function getRequestDecorator(type: Methods) {
  return function post(path: string) {
    return function (target: any, key: string) {
      Reflect.defineMetadata("path", path, target, key);
      Reflect.defineMetadata("method", type, target, key);
    };
  };
}
// 导出方法装饰器工厂函数（注意这里导出的不是装饰器）
export const get = getRequestDecorator(Methods.get);
export const post = getRequestDecorator(Methods.post);
// export const put = getRequestDecorator(Methods.post);
// export const del = getRequestDecorator(Methods.post);
